(in-package :graph-model)

(defclass abstract-arc (marked-mixin) ())

(defclass arc (abstract-arc weight-mixin)
  ((origin :initarg :origin :reader origin)
   (extremity :initarg :extremity :reader extremity))
  (:documentation "an arc of an oriented graph"))

(defmethod compare-object ((a1 arc) (a2 arc))
  (and (eq (origin a1) (origin a2))
       (eq (extremity a1) (extremity a2))))

(defmethod compare-arcs ((a1 arc) (a2 arc))
  (compare-object a1 a2))

(defun make-arc (origin extremity &optional (weight nil))
  (make-instance
   'arc
   :origin origin
   :extremity extremity
   :weight weight))

(defmethod print-object ((arc arc) stream)
  (format stream "~A-~:[~;[~A]~]->~A"
	  (origin arc)
	  (weight arc)
	  (if (weight arc) (weight arc) (extremity arc))
	  (extremity arc)))

(defmethod inverse-arc ((arc arc))
  (make-arc (extremity arc) (origin arc) (weight arc)))

(defmethod mark-arc ((arc arc))
  (mark-object arc))

(defmethod unmark-arc ((arc arc))
  (unmark-object arc))

(defmethod arc-member ((arc arc) (arcs list))
  (member arc arcs :test #'compare-arcs))

(defmethod arc-adjoin ((arc arc) (arcs list))
  (adjoin arc arcs :test #'compare-arcs))

(defmethod arc-remove ((arc arc) (arcs list))
  (remove arc arcs :test #'compare-arcs))

(defmethod arc-union ((arcs1 list) (arcs2 list))
  (union arcs1 arcs2 :test #'compare-arcs))

(defmethod arc-delete-duplicates ((arcs list))
  (delete-duplicates arcs :test #'compare-arcs))

(defmethod arc-remove-duplicates ((arcs list))
  (remove-duplicates arcs :test #'compare-arcs))

(defmethod arc-remove ((arc arc) (arcs list))
  (remove arc arcs :test #'compare-arcs))

(defmethod arc-set-difference ((arcs1 list) (arcs2 list))
  (set-difference arcs1 arcs2 :test #'compare-arcs))

(defmethod arc-subsetp ((arcs1 list) (arcs2 list))
  (subsetp arcs1 arcs2 :test #'compare-arcs))
